﻿using Furion.DatabaseAccessor;
using Furion.DatabaseAccessor.Extensions;
using Furion.DependencyInjection;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using MySql.Data.MySqlClient;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace FurStudy.Core
{
    // 特别注意：在Furion框架中，数据库实体必须直接或间接继承IEntity才能进行仓储等操作

    /// <summary>
    /// IEntity示范
    /// </summary>
    public class User : IEntity
    {
        /// <summary>
        /// 手工定义Id
        /// </summary>
        public int Id { get; set; }

        /// <summary>
        /// 名称
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// 用户名
        /// </summary>
        public string Account { get; set; }

        /// <summary>
        /// 密码
        /// </summary>
        public string PassWord { get; set; }
    }

    /// <summary>
    /// EntityBase示范
    /// </summary>
    public class User2 : EntityBase
    {
        // 无需定义Id属性

        /// <summary>
        /// 名称
        /// </summary>
        public string Name { get; set; }
    }

    /// <summary>
    /// Entity示范
    /// </summary>
    public class User3 : Entity
    {
        // 无需定义Id属性 
        // 并自动添加CreatedTime，UpdatedTime属性

        /// <summary>
        /// 名称
        /// </summary>
        public string Name { get; set; }
    }

    /// <summary>
    /// EntityNotKey示范
    /// </summary>
    public class UserView : EntityNotKey
    {
        public UserView() : base("视图名称")
        {
        }

        /// <summary>
        /// Id
        /// </summary>
        public int Id { get; set; }

        /// <summary>
        /// 名称
        /// </summary>
        public string Name { get; set; }
    }

    /// <summary>
    /// 在数据库实体中配置
    /// </summary>
    public class UserEntityTypeBuilder : Entity, IEntityTypeBuilder<User>
    {
        /// <summary>
        /// 名称
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// 年龄
        /// </summary>
        public int Age { get; set; }

        /// <summary>
        /// 配置数据库实体
        /// </summary>
        /// <param name="entityBuilder"></param>
        /// <param name="dbContext"></param>
        /// <param name="dbContextLocator"></param>
        public void Configure(EntityTypeBuilder<User> entityBuilder, DbContext dbContext, Type dbContextLocator)
        {
            entityBuilder.HasKey(u => u.Id);
            entityBuilder.HasIndex(u => u.Name);
        }
    }

    /// <summary>
    /// 构造函数注入
    /// </summary>
    public class FurionService
    {
        #region 注入

        //private readonly IRepository<Person> _personRepository;

        #endregion

        #region 构造

        //public FurionService(IRepository<Person> personRepository)
        //{
        //    _personRepository = personRepository;
        //}

        #endregion

        #region 仓储高级用法

        // 动态切换实体仓储
        // IRepository<User> userRepository = _personRepository.Change<User>();

        // 动态切换仓储类型
        // 比如，读写分离/主从库仓储：
        // 只读仓储
        // IReadableRepository<User> readRepository = _personRepository.Constraint<IReadableRepository<User>>();

        // 只写仓储
        // IWritableRepository<User> writeRepository = _personRepository.Constraint<IWritableRepository<User>>();

        // Tips：[.Constraint]支持切换任何仓储类型

        // 获取Sql操作仓储
        // var sqlRepository = repository.Sql();

        #endregion

        #region 多数据库操作

        // 切换到 MSSQL 操作 Person表
        // var mssqlRepository = repository.Change<Person, MsSqlDbContextLocator>();

        // 切换到 MySql 操作 Person表
        // var mysqlRepository = repository.Change<Person, MySqlDbContextLocator>();

        // 切换到 Sqlite 操作 Person表
        // var sqliteRepository = repository.Change<Person, SqliteDbContextLocator>();

        // 其他更多数据库一样的操作

        // 另外任何仓储或实体配置都支持多个数据库同时操作
        // 仓储方式
        // IRepository<Person, MsSqlDbContextLocator> mssqlRepository
        // ISqlRepository<MsSqlDbContextLocator> mssqlRepository;
        
        // 动态 sql 方式
        // "select * from person".Change<MsSqlDbContextLocator>().SqlQuery();
        
        // 实体配置方式
        // public class User : Entity<int, MsSqlDbContextLocator, MySqlDbContextLocator>
        // {
        // }
        
        // Sql 代理方式
        // [SqlFunction("funcName", DbContextLocator = typeof(MySqlDbContextLocator))]
        // int GetAge(int id);
        
        // Linq 中方式
        // [QueryableFunction("funcName", "dbo", DbContextLocator = typeof(MySqlDbContextLocator))]
        // string GetName() => throw Oops.Oh("不支持该数据库操作");

        #endregion
    }

    /// <summary>
    /// 方法参数注入
    /// </summary>
    /// <param name="repository"></param>
    /// <param name="keyword"></param>
    /// <returns></returns>
    //public async Task<List<Person>> GetAll([FromServices] IRepository<Person> repository, string keyword)
    //{
    //    var person = await repository.AsQueryable().ToListAsync();
    //    return person.Adapt<List<PersonDto>>();
    //}

    /// <summary>
    /// 不管采用哪种方式，Furion都保证了仓储一次请求唯一性。同时Db.GetRepository<TEntity>()方式支持任何静态类中使用
    /// </summary>
    public class UserInjection
    {
        // 非泛型仓储
        IRepository repository = Db.GetRepository();

        // 泛型仓储
        // var repository2 = Db.GetRepository<Person>();

        // Sql仓储
        ISqlRepository sqlRepository = Db.GetSqlRepository();
    }

    #region 数据库操作（增删改查）


    /// 下文中：
    /// 所有带Now结尾的表示立即提交到数据库，也就是立即调用SaveChanges或SaveChangesAsync
    /// 所有带Exists的表示存在才操作xx列
    /// 所有带Include的表示操作部分列
    /// 所有带Exclude的表示排除特定部分列操作
    /// 所有带IncludeExists的表示数据存在才操作部分列
    /// 所有带ExcludeExists的表示数据存在才排除特定部分列操作

    /// <summary>
    /// 数据库操作 - 新增操作
    /// </summary>
    public class DBInsert
    {
        #region 新增一条，无返回值

        //var user = new User { Name = "百小僧", Age = 27 };

        //// ==== 同步操作 ====

        //// 示例一
        //repository.Insert(user);

        //// 示例二
        //user.Insert();

        //// 示例三
        //repository.Entities.Add(user);

        //// 示例四
        //repository.ChangeEntityState(user, EntityState.Added);

        //// ==== 异步操作 ====

        //// 示例一
        //await repository.InsertAsync(user);

        //// 示例二
        //await user.InsertAsync();

        //// 示例三
        //await repository.Entities.AddAsync(user);


        #endregion

        #region 新增一条，返回最新数据

        //// ==== 同步操作 ====

        //// 示例一
        //var newEntity = repository.InsertNow(user);

        //// 示例三
        //var newEntity = user.InsertNow();

        //// ==== 异步操作 ====

        //// 示例二
        //var newEntity = await repository.InsertNowAsync(user); // 有三个重载

        //// 示例四
        //var newEntity = await user.InsertNowAsync();  // 有三个重载

        #endregion

        #region 新增多条（不立即提交）

        //// ==== 同步操作 ====

        //// 示例一
        //repository.Insert(user, user2);

        //// 示例二
        //repository.Insert(new List<User> { user, user2});

        //// 示例三
        //repository.Insert(new[] {user, user2});

        //// ==== 异步操作 ====

        //// 示例一
        //await repository.InsertAsync(user, user2);

        //// 示例二
        //await repository.InsertAsync(new List<User> { user, user2 });

        //// 示例三
        //await repository.InsertAsync(new[] { user, user2 });

        #endregion

        #region 新增多条（立即提交）

        //// ==== 同步操作 ====

        //// 示例一
        //repository.InsertNow(user, user2);

        //// 示例二
        //repository.InsertNow(new List<User> { user, user2});

        //// 示例三
        //repository.InsertNow(new[] {user, user2});

        //// ==== 异步操作 ====

        //// 示例一
        //await repository.InsertNowAsync(user, user2);

        //// 示例二
        //await repository.InsertNowAsync(new List<User> { user, user2 });

        //// 示例三
        //await repository.InsertNowAsync(new[] { user, user2 });

        #endregion
    }

    /// <summary>
    /// 数据库操作 - 更新操作
    /// </summary>
    public class DBUpdate
    {
        #region 更新全部列（不立即提交）

        //// ==== 同步操作 ====

        //// 示例一
        //repository.Update(user);

        //// 示例二
        //user.Update();

        //// 示例三
        //repository.ChangeEntityState(user, EntityState.Modified);

        //// 示例四
        //repository.Entities.Update(user);

        //// ==== 异步操作 ====

        //// 示例一
        //await repository.UpdateAsync(user);

        //// 示例二
        //await user.UpdateAsync();

        #endregion

        #region 更新全部列（立即提交）

        //// ==== 同步操作 ====

        //// 示例一
        //repository.UpdateNow(user);

        //// 示例二
        //user.UpdateNow();

        //// ==== 异步操作 ====

        //// 示例一
        //await repository.UpdateNowAsync(user);

        //// 示例二
        //await user.UpdateNowAsync();

        #endregion

        #region 更新部分列（不立即提交）

        //// ==== 同步操作 ====

        //// 示例一
        //repository.UpdateInclude(user, new[] {"Age", "Name"});

        //// 示例二
        //repository.UpdateInclude(user, new[] {nameof(User.Name), nameof(User.Age)});

        //// 示例三
        //repository.UpdateInclude(user, new[] { nameof(User.Name), nameof(User.Age) }, true);  // 忽略空值

        //// 示例四
        //user.UpdateInclude(new[] { "Age", "Name" });

        //// 示例五
        //user.UpdateInclude(new[] { nameof(User.Name), nameof(User.Age) });

        //// 示例六
        //user.UpdateInclude(new[] { nameof(User.Name), nameof(User.Age) }, true);  // 忽略空值


        //// ==== 异步操作 ====

        //// 示例一
        //await repository.UpdateIncludeAsync(user, new[] { "Age", "Name" });

        //// 示例二
        //await repository.UpdateIncludeAsync(user, new[] { nameof(User.Name), nameof(User.Age) });

        //// 示例三
        //await repository.UpdateIncludeAsync(user, new[] { nameof(User.Name), nameof(User.Age) }, true);  // 忽略空值

        //// 示例四
        //await user.UpdateIncludeAsync(new[] { "Age", "Name" });

        //// 示例五
        //await user.UpdateIncludeAsync(new[] { nameof(User.Name), nameof(User.Age) });

        //// 示例六
        //await user.UpdateIncludeAsync(new[] { nameof(User.Name), nameof(User.Age) }, true);  // 忽略空值

        #endregion

        #region 更新部分列（立即提交）

        //// ==== 同步操作 ====

        //// 示例一
        //repository.UpdateIncludeNow(user, new[] {"Age", "Name"});

        //// 示例二
        //repository.UpdateIncludeNow(user, new[] {nameof(User.Name), nameof(User.Age)});

        //// 示例三
        //repository.UpdateIncludeNow(user, new[] { nameof(User.Name), nameof(User.Age) }, true);  // 忽略空值

        //// 示例四
        //user.UpdateIncludeNow(new[] { "Age", "Name" });

        //// 示例五
        //user.UpdateIncludeNow(new[] { nameof(User.Name), nameof(User.Age) });

        //// 示例六
        //user.UpdateInclude(new[] { nameof(User.Name), nameof(User.Age) }, true);  // 忽略空值


        //// ==== 异步操作 ====

        //// 示例一
        //await repository.UpdateIncludeNowAsync(user, new[] { "Age", "Name" });

        //// 示例二
        //await repository.UpdateIncludeNowAsync(user, new[] { nameof(User.Name), nameof(User.Age) });

        //// 示例三
        //await repository.UpdateIncludeNowAsync(user, new[] { nameof(User.Name), nameof(User.Age) }, true);  // 忽略空值

        //// 示例四
        //await user.UpdateIncludeNowAsync(new[] { "Age", "Name" });

        //// 示例五
        //await user.UpdateIncludeNowAsync(new[] { nameof(User.Name), nameof(User.Age) });

        //// 示例六
        //await user.UpdateIncludeNowAsync(new[] { nameof(User.Name), nameof(User.Age) }, true);  // 忽略空值

        #endregion

        #region 排除特定列更新（不立即提交）

        //// ==== 同步操作 ====

        //// 示例一
        //repository.UpdateExclude(user, new[] {"Age", "Name"});

        //// 示例二
        //repository.UpdateExclude(user, new[] {nameof(User.Name), nameof(User.Age)});

        //// 示例三
        //repository.UpdateExclude(user, new[] { nameof(User.Name), nameof(User.Age) }, true);  // 忽略空值

        //// 示例四
        //user.UpdateExclude(new[] { "Age", "Name" });

        //// 示例五
        //user.UpdateExclude(new[] { nameof(User.Name), nameof(User.Age) });

        //// 示例六
        //user.UpdateExclude(new[] { nameof(User.Name), nameof(User.Age) }, true);  // 忽略空值


        //// ==== 异步操作 ====

        //// 示例一
        //await repository.UpdateExcludeAsync(user, new[] { "Age", "Name" });

        //// 示例二
        //await repository.UpdateExcludeAsync(user, new[] { nameof(User.Name), nameof(User.Age) });

        //// 示例三
        //await repository.UpdateExcludeAsync(user, new[] { nameof(User.Name), nameof(User.Age) }, true);  // 忽略空值

        //// 示例四
        //await user.UpdateExcludeAsync(new[] { "Age", "Name" });

        //// 示例五
        //await user.UpdateExcludeAsync(new[] { nameof(User.Name), nameof(User.Age) });

        //// 示例六
        //await user.UpdateExcludeAsync(new[] { nameof(User.Name), nameof(User.Age) }, true);  // 忽略空值

        #endregion

        #region 排除特定列更新（立即提交）

        //// ==== 同步操作 ====

        //// 示例一
        //repository.UpdateExcludeNow(user, new[] {"Age", "Name"});

        //// 示例二
        //repository.UpdateExcludeNow(user, new[] {nameof(User.Name), nameof(User.Age)});

        //// 示例三
        //repository.UpdateExcludeNow(user, new[] { nameof(User.Name), nameof(User.Age) }, true);  // 忽略空值

        //// 示例四
        //user.UpdateExcludeNow(new[] { "Age", "Name" });

        //// 示例五
        //user.UpdateExcludeNow(new[] { nameof(User.Name), nameof(User.Age) });

        //// 示例六
        //user.UpdateExcludeNow(new[] { nameof(User.Name), nameof(User.Age) }, true);  // 忽略空值


        //// ==== 异步操作 ====

        //// 示例一
        //await repository.UpdateExcludeNowAsync(user, new[] { "Age", "Name" });

        //// 示例二
        //await repository.UpdateExcludeNowAsync(user, new[] { nameof(User.Name), nameof(User.Age) });

        //// 示例三
        //await repository.UpdateExcludeNowAsync(user, new[] { nameof(User.Name), nameof(User.Age) }, true);  // 忽略空值

        //// 示例四
        //await user.UpdateExcludeNowAsync(new[] { "Age", "Name" });

        //// 示例五
        //await user.UpdateExcludeNowAsync(new[] { nameof(User.Name), nameof(User.Age) });

        //// 示例六
        //await user.UpdateExcludeNowAsync(new[] { nameof(User.Name), nameof(User.Age) }, true);  // 忽略空值

        #endregion

        #region 数据存在才更新所有列（不立即提交）

        //// ==== 同步操作 ====

        //// 示例一
        //repository.UpdateExists(user);

        //// ==== 异步操作 ====

        //// 示例一
        //await repository.UpdateExistsAsync(user);

        #endregion

        #region 数据存在才更新所有列（立即提交）

        //// ==== 同步操作 ====

        //// 示例一
        //repository.UpdateExistsNow(user);

        //// ==== 异步操作 ====

        //// 示例一
        //await repository.UpdateExistsNowAsync(user);

        #endregion

        #region 数据存在才更新部分列（不立即提交）

        //// ==== 同步操作 ====

        //// 示例一
        //repository.UpdateIncludeExists(user, new[] {"Age", "Name"});

        //// 示例二
        //repository.UpdateIncludeExists(user, new[] {nameof(User.Name), nameof(User.Age)});

        //// 示例三
        //repository.UpdateIncludeExists(user, new[] { nameof(User.Name), nameof(User.Age) }, true);  // 忽略空值

        //// ==== 异步操作 ====

        //// 示例一
        //await repository.UpdateIncludeExistsAsync(user, new[] { "Age", "Name" });

        //// 示例二
        //await repository.UpdateIncludeExistsAsync(user, new[] { nameof(User.Name), nameof(User.Age) });

        //// 示例三
        //await repository.UpdateIncludeExistsAsync(user, new[] { nameof(User.Name), nameof(User.Age) }, true);  // 忽略空值

        #endregion

        #region 数据存在才更新部分列（立即提交）

        //// ==== 同步操作 ====

        //// 示例一
        //repository.UpdateIncludeExistsNow(user, new[] {"Age", "Name"});

        //// 示例二
        //repository.UpdateIncludeExistsNow(user, new[] {nameof(User.Name), nameof(User.Age)});

        //// 示例三
        //repository.UpdateIncludeExistsNow(user, new[] { nameof(User.Name), nameof(User.Age) }, true);  // 忽略空值

        //// ==== 异步操作 ====

        //// 示例一
        //await repository.UpdateIncludeExistsNowAsync(user, new[] { "Age", "Name" });

        //// 示例二
        //await repository.UpdateIncludeExistsNowAsync(user, new[] { nameof(User.Name), nameof(User.Age) });

        //// 示例三
        //await repository.UpdateIncludeExistsNowAsync(user, new[] { nameof(User.Name), nameof(User.Age) }, true);  // 忽略空值

        #endregion

        #region 数据存在才排除特定部分列更新（不立即提交）

        //// ==== 同步操作 ====

        //// 示例一
        //repository.UpdateExcludeExists(user, new[] {"Age", "Name"});

        //// 示例二
        //repository.UpdateExcludeExists(user, new[] {nameof(User.Name), nameof(User.Age)});

        //// 示例三
        //repository.UpdateExcludeExists(user, new[] { nameof(User.Name), nameof(User.Age) }, true);  // 忽略空值

        //// ==== 异步操作 ====

        //// 示例一
        //await repository.UpdateExcludeExistsAsync(user, new[] { "Age", "Name" });

        //// 示例二
        //await repository.UpdateExcludeExistsAsync(user, new[] { nameof(User.Name), nameof(User.Age) });

        //// 示例三
        //await repository.UpdateExcludeExistsAsync(user, new[] { nameof(User.Name), nameof(User.Age) }, true);  // 忽略空值

        #endregion

        #region 数据存在才排除特定部分列更新（立即提交）

        //// ==== 同步操作 ====

        //// 示例一
        //repository.UpdateExcludeExistsNow(user, new[] {"Age", "Name"});

        //// 示例二
        //repository.UpdateExcludeExistsNow(user, new[] {nameof(User.Name), nameof(User.Age)});

        //// 示例三
        //repository.UpdateExcludeExistsNow(user, new[] { nameof(User.Name), nameof(User.Age) }, true);  // 忽略空值

        //// ==== 异步操作 ====

        //// 示例一
        //await repository.UpdateExcludeExistsNowAsync(user, new[] { "Age", "Name" });

        //// 示例二
        //await repository.UpdateExcludeExistsNowAsync(user, new[] { nameof(User.Name), nameof(User.Age) });

        //// 示例三
        //await repository.UpdateExcludeExistsNowAsync(user, new[] { nameof(User.Name), nameof(User.Age) }, true);  // 忽略空值

        #endregion

        #region 更新多条记录（不立即提交）

        //// ==== 同步操作 ====

        //// 示例一
        //repository.Update(user, user2);

        //// 示例二
        //repository.Update(new List<User> { user, user2
        //    });

        //// 示例三
        //repository.Update(new[] {user, user2
        //});

        //// ==== 异步操作 ====

        //// 示例一
        //await repository.UpdateAsync(user, user2);

        //// 示例二
        //await repository.UpdateAsync(new List<User> { user, user2 });

        //// 示例三
        //await repository.UpdateAsync(new[] { user, user2 });

        #endregion

        #region 更新多条记录（立即提交）

        //// ==== 同步操作 ====

        //// 示例一
        //repository.UpdateNow(user, user2);

        //// 示例二
        //repository.UpdateNow(new List<User> { user, user2
        //    });

        //// 示例三
        //repository.UpdateNow(new[] {user, user2
        //});

        //// ==== 异步操作 ====

        //// 示例一
        //await repository.UpdateNowAsync(user, user2);

        //// 示例二
        //await repository.UpdateNowAsync(new List<User> { user, user2 });

        //// 示例三
        //await repository.UpdateNowAsync(new[] { user, user2 });

        #endregion

        #region 忽略空值更新

        // 默认情况下，EFCore更新会更新全部列（除实体跟踪方式以外），有些时候我们希望Null值无需更新，这是我们只需要在更新时候配置ignoreNullValues参数即可

        //repository.Update(entity, ignoreNullValues: true);

        #endregion
    }

    /// <summary>
    /// 数据库操作 - 删除操作
    /// </summary>
    public class DBDelete
    {
        #region 删除一个实体（不立即提交）

        //// ==== 同步操作 ====

        //// 示例一
        //repository.Delete(user);

        //// 示例二
        //user.Delete();

        //// 示例三
        //repository.ChangeEntityState(user, EntityState.Deleted);

        //// 示例四
        //repository.Entities.Remove(user);

        //// ==== 异步操作 ====

        //// 示例一
        //await repository.DeleteAsync(user);

        //// 示例二
        //await user.DeleteAsync();

        #endregion

        #region 删除一个实体（立即提交）

        //// ==== 同步操作 ====

        //// 示例一
        //repository.DeleteNow(user);

        //// 示例二
        //user.DeleteNow();

        //// ==== 异步操作 ====

        //// 示例一
        //await repository.DeleteNowAsync(user);

        //// 示例二
        //await user.DeleteNowAsync();

        #endregion

        #region 根据主键删除记录（不立即提交）

        //// ==== 同步操作 ====

        //// 示例一
        //repository.Delete(1);

        //// 示例二
        //user.Delete(1);

        //// ==== 异步操作 ====

        //// 示例一
        //await repository.DeleteAsync(1);

        //// 示例二
        //await user.DeleteAsync(1);

        #endregion

        #region 根据主键删除记录（立即提交）

        //// ==== 同步操作 ====

        //// 示例一
        //repository.DeleteNow(1);

        //// 示例二
        //user.DeleteNow(1);

        //// ==== 异步操作 ====

        //// 示例一
        //await repository.DeleteNowAsync(1);

        //// 示例二
        //await user.DeleteNowAsync(1);

        #endregion
    }

    /// <summary>
    /// 数据库操作 - 批量操作
    /// Furion 框架中，默认只提供小数据（100条以内）批量数据操作
    /// 如果需要更大的数据批量处理，推荐使用第三方包Zack.EFCore.Batch，支持和Furion无缝衔接
    /// </summary>
    public class DBBatch
    {
        // 此处只复制代码，不做执行

        #region 基本使用

        // 批量更新

        //await repository.Context.BatchUpdate<Book>()
        //.Set(b => b.Price, b => b.Price + 3)
        //.Set(b => b.Title, b => s)
        //.Set(b => b.AuthorName, b=>b.Title.Substring(3,2)+b.AuthorName.ToUpper())
        //.Set(b => b.PubTime, b => DateTime.Now)
        //.Where(b => b.Id > n || b.AuthorName.StartsWith("Zack"))
        //.ExecuteAsync();

        // 批量删除

        //await repository.Context.DeleteRangeAsync<Book>(b => b.Price > n || b.AuthorName == "zack yang");

        #endregion

        #region 查询后批量操作

        //// 根据条件批量删除
        //repository.Where(a => a.ItemId >  500).BatchDelete();
        //await repository.Where(a => a.ItemId >  500).BatchDeleteAsync();

        //// 根据条件批量更新
        //repository.Where(a => a.ItemId <= 500).BatchUpdate(a => new Item { Quantity = a.Quantity + 100 });
        //repository.Where(a => a.ItemId <= 500).BatchUpdate(new Item { Description = "Updated" });
        //await repository.Where(a => a.ItemId <= 500).BatchUpdateAsync(new Item { Description = "Updated" });

        //// 批量更新指定列
        //var updateColumns = new List<string> { nameof(Item.Quantity) };
        //var q = repository.Where(a => a.ItemId <= 500);
        //int affected = q.BatchUpdate(new Item { Description = "Updated" }, updateColumns);

        #endregion

        #region 常见批量操作（通过Nuget安装EFCore.BulkExtensions包即可）

        // 批量插入
        //repository.Context.BulkInsert(entitiesList);
        //repository.Context.BulkInsertAsync(entitiesList);

        //// 批量更新
        //repository.Context.BulkUpdate(entitiesList);
        //repository.Context.BulkUpdateAsync(entitiesList);

        //// 批量删除
        //repository.Context.BulkDelete(entitiesList);
        //repository.Context.BulkDeleteAsync(entitiesList);

        //// 批量插入或更新
        //repository.Context.BulkInsertOrUpdate(entitiesList);
        //repository.Context.BulkInsertOrUpdateAsync(entitiesList);

        //// 批量插入或更新或删除
        //repository.Context.BulkInsertOrUpdateOrDelete(entitiesList);
        //repository.Context.BulkInsertOrUpdateOrDeleteAsync(entitiesList);

        //// 批量读取多个实体
        //repository.Context.BulkRead(entitiesList);
        //repository.Context.BulkReadAsync(entitiesList);

        //// 批量清空表（慎用！！！！！）
        //repository.Context.Truncate<Entity>();
        //repository.Context.TruncateAsync<Entity>();

        #endregion
    }

    /// <summary>
    /// 数据库操作 - 查询操作
    /// </summary>
    public class DBFind
    {
        #region 根据主键查询一条

        // Tip：可以支持多个键查询，如主键、联合键。repository.Find(1, "百小僧");

        //// ==== 同步操作 ====

        //// 示例一
        //var person = repository.Find(1);

        //// 示例二
        //var person = repository.FindOrDefault(1);

        //// 示例三
        //var person = repository.Entities.Find(1);

        //// ==== 异步操作 ====

        //// 示例一
        //var person = await repository.FindAsync(1);

        //// 示例二
        //var person = await repository.FindOrDefaultAsync(1);

        //// 示例三
        //var person = await repository.Entities.FindAsync(1);


        #endregion

        #region 根据条件查询一条

        //// ==== 同步操作 ====

        //// 示例一
        //var person = repository.Single(u => u.Name == "Furion");

        //// 示例二
        //var person = repository.SingleOrDefault(u => u.Name == "Furion");

        //// 示例三
        //var person = repository.First(u => u.Name == "Furion");

        //// 示例四
        //var person = repository.FirstOrDefault(u => u.Name == "Furion");

        //// 示例五
        //var person = repository.Last(u => u.Name == "Furion");

        //// 示例六
        //var person = repository.LastOrDefault(u => u.Name == "Furion");

        //// 示例七
        //var person = repository.Entities.Single(u => u.Name == "Furion");

        //// 示例八
        //var person = repository.Entities.First(u => u.Name == "Furion");

        //// 示例九
        //var person = repository.Entities.FirstOrDefault(u => u.Name == "Furion");

        //// 示例十
        //var person = repository.Entities.Last(u => u.Name == "Furion");

        //// 示例十一
        //var person = repository.Entities.LastOrDefault(u => u.Name == "Furion");

        //// ==== 异步操作 ====

        //// 示例一
        //var person = await repository.SingleAsync(u => u.Name == "Furion");

        //// 示例二
        //var person = await repository.SingleOrDefaultAsync(u => u.Name == "Furion");

        //// 示例三
        //var person = await repository.FirstAsync(u => u.Name == "Furion");

        //// 示例四
        //var person = await repository.FirstOrDefaultAsync(u => u.Name == "Furion");

        //// 示例五
        //var person = await repository.LastAsync(u => u.Name == "Furion");

        //// 示例六
        //var person = await repository.LastOrDefaultAsync(u => u.Name == "Furion");

        //// 示例七
        //var person = await repository.Entities.SingleAsync(u => u.Name == "Furion");

        //// 示例八
        //var person = await repository.Entities.FirstAsync(u => u.Name == "Furion");

        //// 示例九
        //var person = await repository.Entities.FirstOrDefaultAsync(u => u.Name == "Furion");

        //// 示例十
        //var person = await repository.Entities.LastAsync(u => u.Name == "Furion");

        //// 示例十一
        //var person = await repository.Entities.LastOrDefaultAsync(u => u.Name == "Furion");

        #endregion

        #region 查询所有数据

        //// ==== 同步操作 ====

        //// 示例一
        //var persons = repository.Entities;

        //// 示例二
        //var persons = repository.DetachedEntities;

        //// 示例三
        //var persons = repository.AsQueryable();

        //// 示例四
        //var persons = repository.AsEnumerable();

        //// 示例五
        //var persons = await repository.AsQueryable().ToListAsync();

        #endregion

        #region 根据条件查询所有数据

        //// 示例一
        //var persons = repository.Where(u => u.Id > 10);

        //// 示例二
        //var persons = repository.Where(u => u.Id > 10 && u.Name.Equals("Furion"));

        //// 示例三  (多个 where 里是 "并且"，Id>10 and Name == "Furion")
        //var persons = repository.Where(u => u.Id > 10).Where(u => u.Name.Equals("Furion"));

        //// 示例四 (判断 name 是否有值，如果 name 是空的则不会执行 u => u.Id > 10 && u.Name.Equals("Furion")，如果 name 有值就会执行 u => u.Id > 10 && u.Name.Equals("Furion"))
        //var persons = repository.Where(!string.IsNullOrEmpty(name), u => u.Id > 10 && u.Name.Equals("Furion"));

        //// 示例五
        //var persons = repository.Where(!string.IsNullOrEmpty(name), u => u.Id > 10)
        //                        .Where(age > 18, u => u.Name.Contains("百小僧"))
        //                        .Where(u => u.Age > 18);

        //// 示例六 (在一个 where 里用逗号分隔是 "或者"，Name=="Furion" or Name == "百小僧" or Name == "MonkSoul")
        //var persons = repository.Where(u => u.Name == "Furion",
        //                                 u => u.Name == "百小僧",
        //                                 u => u.Name == "MonkSoul");

        //// 示例七
        //var persons = repository.Where(u => u.Id > 10).Where(u => u.Name.Equals("Furion"))
        //                        .Where(age > 18, u => u.Name.Contains("百小僧"))
        //                        .Where(u => u.Name == "Furion",
        //                                 u => u.Name == "百小僧",
        //                                 u => u.Name == "MonkSoul");

        //// 示例八
        //var persons = repository.Where((age > 18, u => u.Name == "Furion"),
        //                                   (!string.IsNullOrEmpty(name), u => u.Id > 10));

        //// 示例九
        //var persons = repository.Where(u => u.Id > 10).Where(u => u.Name.Equals("Furion"))
        //                        .Where(age > 18, u => u.Name.Contains("百小僧"))
        //                        .Where(u => u.Name == "Furion",
        //                                 u => u.Name == "百小僧",
        //                                 u => u.Name == "MonkSoul")
        //                        .Where((age > 18, u => u.Name == "Furion"),
        //                                   (!string.IsNullOrEmpty(name), u => u.Id > 10));

        //// 示例十
        //var persons = repository.Entities.Where(u => u.Id > 10)
        //                                 .Where(age > 18, u => u.Name.Contains("百小僧"));

        //// 示例十一
        //var persons = repository.DetachedEntities.Where(u => u.Id > 20);

        //// 示例十二
        //var persons = repository.AsQueryable(u => u.Id > 20).Where(u => u.Name == "Furion");

        #endregion

        #region 分页查询

        //// ==== 同步操作 ====

        //// 示例一
        //var persons = repository.Where(u => u.Id > 10).ToPagedList();

        //// 示例二
        //var persons = repository.Where(u => u.Id > 10).ToPagedList(1, 10);

        //// ==== 异步操作 ====

        //// 示例一
        //var persons = await repository.Where(u => u.Id > 10).ToPagedListAsync();

        //// 示例二
        //var persons = await repository.Where(u => u.Id > 10).ToPagedListAsync(1, 10);

        #endregion

        #region 其他查询

        #region 查看记录是否存在

        //// ==== 同步操作 ====

        //// 示例一
        //var isExists = repository.Any();

        //// 示例二
        //var isExists = repository.Any(u => u.Id > 10);

        //// 示例三
        //var isExists = repository.Entities.Any();

        //// 示例四
        //var isExists = repository.DetachedEntities.Any(u => u.Id > 10);

        //// 示例五
        //var isExists = repository.Where(u => u.Id > 10).Any();

        //// ==== 异步操作 ====

        //// 示例一
        //var isExists = await repository.AnyAsync();

        //// 示例二
        //var isExists = await repository.AnyAsync(u => u.Id > 10);

        //// 示例三
        //var isExists = await repository.Entities.AnyAsync();

        //// 示例四
        //var isExists = await repository.DetachedEntities.AnyAsync(u => u.Id > 10);

        //// 示例五
        //var isExists = await repository.Where(u => u.Id > 10).AnyAsync();

        #endregion

        #region 查看记录数

        //// ==== 同步操作 ====

        //// 示例一
        //var count = repository.Count();

        //// 示例二
        //var count = repository.Count(u => u.Id > 10);

        //// 示例三
        //var count = repository.Entities.Count(u => u.Id > 10);

        //// 示例四
        //var count = repository.Entities.DetachedEntities.Count();

        //// 示例五
        //var count = repository.Where(u => u.Id > 10).Count();

        //// ==== 异步操作 ====

        //// 示例一
        //var count = await repository.CountAsync();

        //// 示例二
        //var count = await repository.CountAsync(u => u.Id > 10);

        //// 示例三
        //var count = await repository.Entities.CountAsync(u => u.Id > 10);

        //// 示例四
        //var count = await repository.Entities.DetachedEntities.CountAsync();

        //// 示例五
        //var count = await repository.Where(u => u.Id > 10).CountAsync();

        #endregion

        #region 查询最大值

        //// ==== 同步操作 ====

        //// 示例一
        //var entity = repository.Max();

        //// 示例二
        //var value = repository.Max(u => u.Id);

        //// 示例三
        //var entity = repository.Entities.Max();

        //// 示例四
        //var value = repository.Entities.DetachedEntities.Max(u => u.Age);

        //// 示例五
        //var value = repository.Where(u => u.Id > 10).Max(u => u.Age);

        //// ==== 异步操作 ====

        //// 示例一
        //var entity = await repository.MaxAsync();

        //// 示例二
        //var value = await repository.MaxAsync(u => u.Id);

        //// 示例三
        //var entity = await repository.Entities.MaxAsync();

        //// 示例四
        //var value = await repository.Entities.DetachedEntities.MaxAsync(u => u.Age);

        //// 示例五
        //var value = await repository.Where(u => u.Id > 10).MaxAsync(u => u.Age);

        #endregion

        #region 查询最小值

        //// ==== 同步操作 ====

        //// 示例一
        //var entity = repository.Min();

        //// 示例二
        //var value = repository.Min(u => u.Id);

        //// 示例三
        //var entity = repository.Entities.Min();

        //// 示例四
        //var value = repository.Entities.DetachedEntities.Min(u => u.Age);

        //// 示例五
        //var value = repository.Where(u => u.Id > 10).Min(u => u.Age);

        //// ==== 异步操作 ====

        //// 示例一
        //var entity = await repository.MinAsync();

        //// 示例二
        //var value = await repository.MinAsync(u => u.Id);

        //// 示例三
        //var entity = await repository.Entities.MinAsync();

        //// 示例四
        //var value = await repository.Entities.DetachedEntities.MinAsync(u => u.Age);

        //// 示例五
        //var value = await repository.Where(u => u.Id > 10).MinAsync(u => u.Age);

        #endregion

        #region 求和查询

        //// ==== 同步操作 ====

        //// 示例一
        //var sum = repository.Entities.Sum(u => u.Cost);

        //// 示例二
        //var sum = repository.AsQueryable().Sum(u => u.Cost);

        //// 示例三
        //var sum = repository.DetachedEntities.Sum(u => u.Cost);

        //// ==== 异步操作 ====

        //// 示例一
        //var sum = await repository.Entities.SumAsync(u => u.Cost);

        //// 示例二
        //var sum = await repository.AsQueryable().SumAsync(u => u.Cost);

        //// 示例三
        //var sum = await repository.DetachedEntities.SumAsync(u => u.Cost);

        #endregion

        #region 求平均值查询

        //// ==== 同步操作 ====

        //// 示例一
        //var sum = repository.Entities.Average(u => u.Cost);

        //// 示例二
        //var sum = repository.AsQueryable().Average(u => u.Cost);

        //// 示例三
        //var sum = repository.DetachedEntities.Average(u => u.Cost);

        //// ==== 异步操作 ====

        //// 示例一
        //var sum = await repository.Entities.AverageAsync(u => u.Cost);

        //// 示例二
        //var sum = await repository.AsQueryable().AverageAsync(u => u.Cost);

        //// 示例三
        //var sum = await repository.DetachedEntities.AverageAsync(u => u.Cost);

        #endregion

        #region 时间查询

        //var starDate = DateTime.Parse("2020-09-10");
        //var endDate = DateTime.Parse("2020-09-10");
        //var query = repository.Where(u => u.CreatedDt >= starDate && u.CreatedDt <= endDate);

        #endregion

        #region 模糊查询

        //// 示例一
        //repository.Where(u => u.Name.StartWith("Furion"));

        //// 示例二
        //_testRepository.Where(u => u.Name.EndWith("Furion"));

        //// 示例三
        //_testRepository.Where(u => u.Name.Contains("Furion"));

        #endregion

        #region Case When

        // 数据库中的Case When实际上对应的是我们程序中的三元表达式，也就是使用三元表达式即可自动生成Case When语句

        #endregion

        #endregion
    }

    /// <summary>
    /// 数据库操作 - 高级查询
    /// </summary>
    public class DBAdvancedQuery
    {
        #region 一对一查询

        //// 示例一
        //var person = repository.Include(u => u.Detail);

        //// 示例二
        //var person = repository.Include(u => u.Detail)
        //                       .Include(u => u.Post);

        //// 示例三
        //var person = repository.Include(u => u.Detail)
        //                            .ThenInclude(d => d.Review)
        //                       .Include(u => u.Post);

        //// 示例四
        //var person = repository.Include(u => u.Detail.Where(d => d.Id > 10).OrderBy(d => d.Name))
        //                            .ThenInclude(d => d.Review)
        //                       .Include(u => u.Post);

        //// 示例五
        //var person = repository.Include(!string.IsNullOrEmpty(keyword), u => u.Detail);

        //// 示例六
        //var person = repository.Include(!string.IsNullOrEmpty(keyword), u => u.Detail)
        //                       .Include(age > 18, u => u.Detail.Where(d => d.Id > 10).OrderBy(d => d.Name))
        //                            .ThenInclude(d => d.Review)
        //                       .Include(u => u.Post);

        #endregion

        #region 一对多查询

        //// 示例一
        //var person = repository.Include(u => u.Childrens);

        //// 参考 一对一 例子

        #endregion

        // 注：一对一和一对多查询方法一样，唯一的区别是：一对多采用ICollection<TEntity>定义属性

        #region 多对多查询

        //// 示例一
        //var person = repository.Include(u => u.Posts);

        //// 参考 一对一 例子

        #endregion

        // 注：一对一和多对多查询方法一样，唯一的区别是：多对多采用ICollection<TEntity>定义属性

        #region 联表查询

        #region 内连接（Inner Join）

        //var query = from p in _personRepository.AsQueryable()
        //            join d in _personDetailRepository.AsQueryable() on p.Id equals d.PersonId
        //            select new PersonDto
        //            {
        //                PhoneNumber = p.PersonDetail.PhoneNumber,
        //                Address = p.Address,
        //                Age = p.Age,
        //                Name = p.Name,
        //                Id = p.Id,
        //                QQ = p.PersonDetail.QQ
        //            };

        #endregion

        #region 左连接（Left Join）

        //var query = from p in _personRepository.AsQueryable()
        //            join d in _personDetailRepository.AsQueryable() on p.Id equals d.PersonId into results
        //            from d in results.DefaultIfEmpty()
        //            select new PersonDto
        //            {
        //                PhoneNumber = p.PersonDetail.PhoneNumber,
        //                Address = p.Address,
        //                Age = p.Age,
        //                Name = p.Name,
        //                Id = p.Id,
        //                QQ = p.PersonDetail.QQ
        //            };

        #endregion

        // Tip：Left Join和Inner Join不同的是，Left Join会先将结果into到新的结果集然后再查询，并调用DefaultIfEmpty()方法

        #region 右连接（Right Join）

        // Right Join只需要将Left Join主从表位置更换即可

        #endregion

        #region 分组查询

        //// 示例一
        //var query = repository.AsQueryable().GroupBy(x => new { x.Column1, x.Column2 });

        //// 示例二
        //var query = from student in repository.AsQueryable()
        //            group student by repository2.AsQueryable() into dateGroup
        //            select new ResultData()
        //            {
        //                Key = dateGroup.Key,
        //                Value = dateGroup.Count()
        //            };

        //// 示例三
        //var query = from a in repository.AsQueryable()
        //            join b in repository2.AsQueryable() on a.Id equals b.Aid
        //            join c in repository3.AsQueryable() on c.id equals b.Bid
        //            group a by new { a.Age, b.Sex } into g
        //            select new
        //            {
        //                Peo = g.Key,
        //                Count = g.Count()
        //            };

        #endregion

        #region 合并结果集

        //var query = repository.AsQueryable(u => u.Id > 10)
        //              .Union(
        //                  repository2.AsQueryable(u => u.Id <= 10)
        //              );

        #endregion

        #region 查询排序

        #region 正序

        //// 示例一
        //var query = repository.AsQueryable()
        //                      .OrderBy(u => u.Id);

        //// 示例二
        //var query = repository.AsQueryable()
        //                     .OrderBy(u => u.Id)
        //                     .ThenBy(u => u.Name);

        #endregion

        #region 倒序

        //// 示例一
        //var query = repository.AsQueryable()
        //                      .OrderByDescending(u => u.Id);

        //// 示例二
        //var query = repository.AsQueryable()
        //                     .OrderByDescending(u => u.Id)
        //                     .ThenByDescending(u => u.Name);

        #endregion

        #region 混合倒序

        //// 示例一
        //var query = repository.AsQueryable()
        //                      .OrderBy(u => u.Id)
        //                      .OrderByDescending(u => u.Name)
        //                      .ThenBy(u => u.Age);

        #endregion

        #endregion

        #region 递归查询

        //var cities = await repository.AsQueryable()
        //                     .Include(u => u.Childrens)
        //                     .Where(u => u.Id == 1)
        //                     .ToListAsync();

        //var dtos = cities.Adapt<List<CityDto>>();

        #endregion

        #region 动态Sql查询

        // Furion默认不支持动态 Sql 查询功能，不过可以通过第三方实现：
        // 在Furion项目层安装System.Linq.Dynamic.Core包 https://github.com/zzzprojects/System.Linq.Dynamic.Core

        #region 动态Sql查询

        //// 示例一
        //var query = repository.AsQueryable()
        //                      .Where("City == @0 and Orders.Count >= @1", "China", 10)
        //                      .OrderBy("CompanyName")
        //                      .Select("new(CompanyName as Name, Phone)");

        //// 示例二
        //var list = repository.AsQueryable()
        //                     .Where("Name.Contains(@0)", "Furion")
        //                     .ToList();

        //// 示例三，支持 ? 语法
        //var customers = repository.AsQueryable()
        //                          .Include(c => c.Location)
        //                          .Where(c => c.Location?.Name == "test") // 注意 Location?.Name
        //                          .ToList();

        #endregion

        #region 动态Lambda

        //// 示例一
        //var x = Expression.Parameter(typeof(int), "x");
        //var y = Expression.Parameter(typeof(int), "y");
        //var e = DynamicExpressionParser
        //            .ParseLambda(new ParameterExpression[] { x, y }, null, "(x + y) * 2");

        //// 示例二
        //var e = DynamicExpressionParser.ParseLambda(
        //        typeof(Customer), typeof(bool),
        //        "City = @0 and Orders.Count >= @1",
        //        "London", 10);

        #endregion

        #endregion

        #region 性能优化

        // 默认情况下，EF Core会跟踪所有实体，也就是任何数据改变都会引起数据检查，所以如果只做查询操作，建议关闭实体跟踪功能。
        // Furion框架提供了以下高性能实体集合：
        // DetachedEntities：脱轨/不追踪实体
        // AsQueryable(false)：不追踪实体
        // Entities.AsNoTracking()：手动关闭实体追踪
        // 在EF Core中，复杂查询总是会生成一个sql，也就是AsSingleQuery()，我们也可以设置为AsSplitQuery()切割成多个查询

        // 分表查询小例子见下方Human类

        // var posts = repository.Where(u => u.Id > 10).ToList();

        #endregion

        #endregion
    }

    /// <summary>
    /// 分表查询小例子
    /// </summary>
    public class Human : Entity, IEntityTypeBuilder<Person>
    {
        public string Name { get; set; }

        /// <summary> 
        /// 配置实体关系
        /// </summary>
        /// <param name="entityBuilder"></param>
        /// <param name="dbContext"></param>
        /// <param name="dbContextLocator"></param>
        public void Configure(EntityTypeBuilder<Person> entityBuilder, DbContext dbContext, Type dbContextLocator)
        {
            entityBuilder.ToSqlQuery(
                @"select * from dbo.person.2020-09-19 
                union all 
                select * from dbp.person.2020-09-20");
        }
    }

    #endregion

    #region 视图

    // 创建视图SQL
    // CREATE VIEW V_Person AS
    // SELECT Id, Name, Age, Address FROM person

    // 视图使用
    // 视图除了不能操作（写）以外，其他操作和表操作无异
    // var vEntities = v_repository.Where(u => u.Id > 10).ToList();

    #endregion

    #region 函数的使用

    /// <summary>
    /// Furion框架每一个数据库操作都支持异步方式
    /// </summary>
    public class Function
    {
        #region 标量函数返回object

        //// ISqlRepository 方法
        //var value = _sqlRepository.SqlFunctionScalar("func_GetValue");

        //// ISqlDispatchProxy 方式
        //var value = _sqlExecuteProxy.GetValue();  // 推荐方式

        //// 实体仓储方式
        //var value = _personRepository.SqlFunctionScalar("func_GetValue");

        //// IRepository 非泛型方式
        //var value = _repository.Sql().SqlFunctionScalar("func_GetValue");

        //// 变态懒人方式，直接通过函数名执行
        //var value = "func_GetValue".SqlFunctionScalar();

        #endregion

        #region 标量函数返回T

        //// ISqlRepository 方法
        //var value = _sqlRepository.SqlFunctionScalar<string>("func_GetValue");

        //// ISqlDispatchProxy 方式
        //var value = _sqlExecuteProxy.GetValue();  // 推荐方式

        //// 实体仓储方式
        //var value = _personRepository.SqlFunctionScalar<string>("func_GetValue");

        //// IRepository 非泛型方式
        //var value = _repository.Sql().SqlFunctionScalar<string>("func_GetValue");

        //// 变态懒人方式，直接通过函数名执行
        //var value = "func_GetValue".SqlFunctionScalar<string>();

        #endregion

        #region 表值函数返回DataTable

        //// ISqlRepository 方法
        //var value = _sqlRepository.SqlFunctionQuery("func_GetTable");

        //// ISqlDispatchProxy 方式
        //var value = _sqlExecuteProxy.GetTable();  // 推荐方式

        //// 实体仓储方式
        //var value = _personRepository.SqlFunctionQuery("func_GetTable");

        //// IRepository 非泛型方式
        //var value = _repository.Sql().SqlFunctionQuery("func_GetTable");

        //// 变态懒人方式，直接通过函数名执行
        //var value = "func_GetTable".SqlFunctionQuery();

        #endregion

        #region 表值函数返回List<T>

        //// ISqlRepository 方法
        //var value = _sqlRepository.SqlFunctionQuery<Person>("func_GetTable");

        //// ISqlDispatchProxy 方式
        //var value = _sqlExecuteProxy.GetTable();  // 推荐方式

        //// 实体仓储方式
        //var value = _personRepository.SqlFunctionQuery<Person>("func_GetTable");

        //// IRepository 非泛型方式
        //var value = _repository.Sql().SqlFunctionQuery<Person>("func_GetTable");

        //// 变态懒人方式，直接通过函数名执行
        //var value = "func_GetTable".SqlFunctionQuery<Person>();

        #endregion

        #region 在Linq中使用标量函数

        // Furion框架提供非常灵活的在Linq中使用标量函数的方法。如果像使用这样的方式，需要满足以下两个条件：
        // 标量函数必须定义在公开静态类中，且自己也是公开静态方法
        // 该公开静态方法必须贴有[QueryableFunction]特性

        #region 创建标量函数

        //CREATE FUNCTION FN_GetId
        //(
        //    @id INT
        //)
        //RETURNS INT
        //AS
        //BEGIN
        //    RETURN @id + 1;
        //END;

        #endregion

        #region 创建静态类和静态方法

        // 见下方QueryFunctions类

        #endregion

        #region 在Linq中使用

        // _personRepository.Where(u => u.Id > QueryFunctions.GetId(1)).ToList();

        // SELECT [p].[Id], [p].[Address], [p].[Age], [p].[CreatedTime], [p].[IsDeleted], [p].[Name], [p].[UpdatedTime]
        // FROM[Person] AS[p]
        // WHERE[p].[Id] > [dbo].[FN_GetId] (1)    // 💥 注意这里


        #endregion

        #endregion

        #region 在Linq中使用表值函数

        // EF Core 5.0版本支持在Linq中操作表值函数，操作有点类似视图操作

        #region 创建表值函数

        //CREATE FUNCTION dbo.GetPersons
        //(
        //    @id INT
        //)
        //RETURNS TABLE
        //AS
        //RETURN
        //(
        //    SELECT Id,
        //           Name,
        //           Age,
        //           Address
        //    FROM dbo.Person
        //    WHERE Id > @id
        //);

        #endregion

        #region 创建表值函数模型

        // 见F_Person类

        #endregion

        #region 表值函数配置

        // 见FurionDbContext - OnModelCreating()

        #endregion

        #region 在Linq中使用

        // IQueryable<F_Person> query = _repository.DynamicDbContext.GetPersons(1);
        // var result = query.Where(u => u.Name.Equals("Furion")).ToList();

        // 最终生成sql
        // SELECT[g].Id, [g].Name, [g].Age, [g].Address
        // FROM dbo.GetPersons(1) AS[g]
        // WHERE [g].Name == N'Furion';

        #endregion

        #endregion

        #region 在EF Core内置函数

        // EF Core为我们提供了很多常用的内置函数，可以在Lambda条件中使用，主要是通过EF.Functions调用
        // _repository.Where(u => EF.Functions.DateDiffHour(u.CreatedDt, DateTime.Now) > 8).FirstOrDefault();

        // 这个语句使用了EF.Functions.DateDiffHour最终生成的Sql如下：
        // SELECT TOP(1) [a].*
        // FROM [dbo].[TEST]
        // AS [a]
        // WHERE DATEDIFF(HOUR, [a].[CREATED_DT], GETDATE()) > 8

        // EF Core内置函数就不一一列出了，可以通过EF.Functions查看更多，如果不能满足自己的需求，那么可以自定义Linq标量函数

        #endregion
    }

    /// <summary>
    /// 创建静态类，将标量函数放在静态类中
    /// 必须是公开静态的
    /// </summary>
    public static class QueryFunctions
    {
        /// <summary>
        /// 配置标量函数
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [QueryableFunction("FN_GetId", "dbo")]
        public static int GetId(int id)
        {
            throw new NotSupportedException();
        }
    }

    #endregion

    #region Sql操作

    // 例子说明
    // 本章节例子均以sql server数据库写的例子，命令参数统一用@符号，但不同数据库的参数前缀有所不同，如：sql server采用@，oracle采用:，mysql采用?

    #region 懒人无敌Sql

    #region 返回DataTable

    // SqlQuery：返回DataTable

    //// ==== 同步操作 ====

    //// 示例一
    //var dataTable = "select * from person".SqlQuery();

    //// 示例二
    //var dataTable = "select top 10 * from person where id > @id".SqlQuery(new { id = 10 });

    //// 示例三
    //var dataTable = "select Id, Name, Age from person where name like @name".SqlQuery(new Dictionary<string, object> { { "name", "%Furion%" } });

    //// 示例四
    //var dataTable = "select * from person where name=@name limit 1,10".SqlQuery(new[] { new MySqlParameter("name", "Furion") });

    //// 示例五
    //var dataTable = "select * from person where id>@id and name like @name".SqlQuery(new YourModel { Id = 1, Name = "%Furion%" });

    //// 示例六
    //var dataTable = "exec PROC_GetPerson @id".SqlQuery(new { id = 10 });

    //// 示例七
    //var dataTable = "select * from FN_GetPersons(@id)".SqlQuery(new { id = 10 });

    //// 示例八
    //var dataTable = @"
    //select * from person p
    //left join personDetail pd on p.Id == pd.pid
    //where p.Id > @id;".SqlQuery(new { id = 10 });

    //// ==== 异步操作 ====

    //// 示例一
    //var dataTable = await "select * from person".SqlQueryAsync();

    //// 示例二
    //var dataTable = await "select top 10 * from person where id > @id".SqlQueryAsync(new { id = 10 });

    //// 示例三
    //var dataTable = await "select Id, Name, Age from person where name like @name".SqlQueryAsync(new Dictionary<string, object> { { "name", "%Furion%" } });

    //// 示例四
    //var dataTable = await "select * from person where name=@name limit 1,10".SqlQueryAsync(new[] { new MySqlParameter("name", "Furion") });

    //// 示例五
    //var dataTable = await "select * from person where id>@id and name like @name".SqlQueryAsync(new YourModel { Id = 1, Name = "%Furion%" });

    //// 示例六
    //var dataTable = await "exec PROC_GetPerson @id".SqlQueryAsync(new { id = 10 });

    //// 示例七
    //var dataTable = await "select * from FN_GetPersons(@id)".SqlQueryAsync(new { id = 10 });

    //// 示例八
    //var dataTable = await @"
    //select * from person p
    //left join personDetail pd on p.Id == pd.pid
    //where p.Id > @id;".SqlQueryAsync(new { id = 10 });

    #endregion

    #region 返回List<T>

    // SqlQuery：返回List<T>

    // ==== 同步操作 ====

    //// 示例一
    //var persons = "select * from person".SqlQuery<Person>();

    //// 示例二
    //var persons = "select top 10 * from person where id > @id".SqlQuery<Person>(new { id = 10 });

    //// 示例三
    //var persons = "select Id, Name, Age from person where name like @name".SqlQuery<Person>(new Dictionary<string, object> { { "name", "%Furion%" } });

    //// 示例四
    //var persons = "select * from person where name=@name limit 1,10".SqlQuery<Person>(new[] { new MySqlParameter("name", "Furion") });

    //// 示例五
    //var persons = "select * from person where id>@id and name like @name".SqlQuery<Person>(new YourModel { Id = 1, Name = "%Furion%" });

    //// 示例六
    //var persons = "exec PROC_GetPerson @id".SqlQuery<Person>(new { id = 10 });

    //// 示例七
    //var persons = "select * from FN_GetPersons(@id)".SqlQuery<Person>(new { id = 10 });

    //// 示例八
    //var persons = @"
    //select * from person p
    //left join personDetail pd on p.Id == pd.pid
    //where p.Id > @id;".SqlQuery<Person>(new { id = 10 });

    //// ==== 异步操作 ====

    //// 示例一
    //var persons = await "select * from person".SqlQueryAsync<Person>();

    //// 示例二
    //var persons = await "select top 10 * from person where id > @id".SqlQueryAsync<Person>(new { id = 10 });

    //// 示例三
    //var persons = await "select Id, Name, Age from person where name like @name".SqlQueryAsync<Person>(new Dictionary<string, object> { { "name", "%Furion%" } });

    //// 示例四
    //var persons = await "select * from person where name=@name limit 1,10".SqlQueryAsync<Person>(new[] { new MySqlParameter("name", "Furion") });

    //// 示例五
    //var persons = await "select * from person where id>@id and name like @name".SqlQueryAsync<Person>(new YourModel { Id = 1, Name = "%Furion%" });

    //// 示例六
    //var persons = await "exec PROC_GetPerson @id".SqlQueryAsync<Person>(new { id = 10 });

    //// 示例七
    //var persons = await "select * from FN_GetPersons(@id)".SqlQueryAsync<Person>(new { id = 10 });

    //// 示例八
    //var persons = await @"
    //select * from person p
    //left join personDetail pd on p.Id == pd.pid
    //where p.Id > @id;".SqlQueryAsync<Person>(new { id = 10 });

    #endregion

    #region 返回DataSet

    // SqlQueries：返回DataSet

    //// ==== 同步操作 ====

    //// 示例一
    //var dataSet = @"
    //select * from person;
    //select * from student;".SqlQueries();

    //// 示例二
    //var dataSet = @"
    //select * from person where Id > @id;
    //select * from student where Name like @name;".SqlQueries(new { id = 1, name = "%furion%" });

    //// 示例三
    //var dataSet = @"
    //select * from person;
    //exec PROC_GetStudents(@id);
    //select 'Furion';
    //select * from FN_GetPerson(@id);".SqlQueries(new { id = 1 });

    //// ==== 异步操作 ====

    //// 示例一
    //var dataSet = await @"
    //select * from person;
    //select * from student;".SqlQueriesAsync();

    //// 示例二
    //var dataSet = await @"
    //select * from person where Id > @id;
    //select * from student where Name like @name;".SqlQueriesAsync(new { id = 1, name = "%furion%" });

    //// 示例三
    //var dataSet = await @"
    //select * from person;
    //exec PROC_GetStudents(@id);
    //select 'Furion';
    //select * from FN_GetPerson(@id);".SqlQueriesAsync(new { id = 1 });

    #endregion

    #region 返回 Tuple<T1,...T8>

    //// ==== 同步操作 ====

    //// 示例一
    //var(persons, students) = @"
    //select * from person;
    //select * from student;".SqlQueries<Person, Student>();

    //// 示例二
    //var(persons, students) = @"
    //select * from person where Id > @id;
    //select * from student where Name like @name;".SqlQueries<Person, Student>(new {id = 1, name = "%furion%"});

    //// 示例三
    //var(persons, students, string, PersonDto) = @"
    //select * from person;
    //exec PROC_GetStudents(@id);
    //select 'Furion';
    //select * from FN_GetPerson(@id);".SqlQueries<Person, Student, string, PersonDto>(new { id = 1 });

    //// ==== 异步操作 ====

    //// 示例一
    //var (persons, students) = await @"
    //select * from person;
    //select * from student;".SqlQueriesAsync<Person, Student>();

    //// 示例二
    //var (persons, students) = await @"
    //select * from person where Id > @id;
    //select * from student where Name like @name;".SqlQueriesAsync<Person, Student>(new { id = 1, name = "%furion%" });

    //// 示例三
    //var(persons, students, string, PersonDto) = await @"
    //select * from person;
    //exec PROC_GetStudents(@id);
    //select 'Furion';
    //select * from FN_GetPerson(@id);".SqlQueriesAsync<Person, Student, string, PersonDto>(new { id = 1 });

    #endregion

    #region 返回单行单列

    // SqlScalar：返回单行单列

    //// ==== 同步操作 ====

    //// 示例一
    //var value = "select Name from person where id = @id".SqlScalar(new { id = 1 });

    //// 示例二
    //var value = "select Name from person where id = @id".SqlScalar<string>(new { id = 1 });

    //// 示例三
    //var value = "select Age from person where id = @id".SqlScalar<int>(new { id = 1 });

    //// ==== 异步操作 ====

    //// 示例一
    //var value = await "select Name from person where id = @id".SqlScalarAsync(new { id = 1 });

    //// 示例二
    //var value = await "select Name from person where id = @id".SqlScalarAsync<string>(new { id = 1 });

    //// 示例三
    //var value = await "select Age from person where id = @id".SqlScalarAsync<int>(new { id = 1 });

    #endregion

    #region 返回受影响行数

    // ==== 同步操作 ====

    // SqlNonQuery：执行SQL无数据返回 返回结果：Int

    //// 示例一
    //var rowEffects = "insert into person(Name,Age,Address) values(@name,@age,@address)".SqlNonQuery(person);

    //// 示例二
    //var rowEffects = @"
    //insert into person(Name,Age,Address) values(@name,@age,@address);
    //insert into person(Name,Age,Address) values(@name,@age,@address);".SqlNonQuery(persons);

    //// 示例三
    //var rowEffects = "update person set name=@name where id=@id".SqlNonQuery(new { id = 1, name = "百小僧" });

    //// 示例四
    //var rowEffects = "delete from person where @id > 10".SqlNonQuery(new { id = 1 });

    //// ==== 异步操作 ====

    //// 示例一
    //var rowEffects = await "insert into person(Name,Age,Address) values(@name,@age,@address)".SqlNonQueryAsync(person);

    //// 示例二
    //var rowEffects = @"
    //insert into person(Name,Age,Address) values(@name,@age,@address);
    //insert into person(Name,Age,Address) values(@name,@age,@address);".SqlNonQueryAsync(persons);

    //// 示例三
    //var rowEffects = await "update person set name=@name where id=@id".SqlNonQueryAsync(new { id = 1, name = "百小僧" });

    //// 示例四
    //var rowEffects = await "delete from person where @id > 10".SqlNonQueryAsync(new { id = 1 });

    #endregion

    #endregion

    #region 懒人无敌存储过程

    #region 返回DataTable

    // SqlProcedureQuery：执行存储过程返回DataTable 返回结果：DataTable

    // ==== 同步操作 ====

    //// 示例一
    //var dataTable = "PROC_Name".SqlProcedureQuery();

    //// 示例二
    //var dataTable = "PROC_Name".SqlProcedureQuery(new { id = 1 });

    //// 示例三
    //var dataTable = "PROC_Name".SqlProcedureQuery(new { id = 1, age = 27 });

    //// ==== 异步操作 ====

    //// 示例一
    //var dataTable = await "PROC_Name".SqlProcedureQueryAsync();

    //// 示例二
    //var dataTable = await "PROC_Name".SqlProcedureQueryAsync(new { id = 1 });

    //// 示例三
    //var dataTable = await "PROC_Name".SqlProcedureQueryAsync(new { id = 1, age = 27 });

    #endregion

    #region 返回List<T>

    // SqlProcedureQuery：执行存储过程返回List集合 返回结果：List{T}

    //// ==== 同步操作 ====

    //// 示例一
    //var persons = "PROC_Name".SqlProcedureQuery<Person>();

    //// 示例二
    //var persons = "PROC_Name".SqlProcedureQuery<Person>(new { id = 1 });

    //// 示例三
    //var persons = "PROC_Name".SqlProcedureQuery<Person>(new { id = 1, age = 27 });

    //// ==== 异步操作 ====

    //// 示例一
    //var persons = await "PROC_Name".SqlProcedureQueryAsync<Person>();

    //// 示例二
    //var persons = await "PROC_Name".SqlProcedureQueryAsync<Person>(new { id = 1 });

    //// 示例三
    //var persons = await "PROC_Name".SqlProcedureQueryAsync<Person>(new { id = 1, age = 27 });

    #endregion

    #region 返回DataSet

    // SqlProcedureQueries：执行存储过程返回DataSet 返回结果：DataSet

    // ==== 同步操作 ====

    //// 示例一
    //var dataSet = "PROC_Name".SqlProcedureQueries();

    //// 示例二
    //var dataSet = "PROC_Name".SqlProcedureQueries(new { id = 1 });

    //// 示例三
    //var dataSet = "PROC_Name".SqlProcedureQueries(new { id = 1, age = 27 });

    //// ==== 异步操作 ====

    //// 示例一
    //var dataSet = await "PROC_Name".SqlProcedureQueriesAsync();

    //// 示例二
    //var dataSet = await "PROC_Name".SqlProcedureQueriesAsync(new { id = 1 });

    //// 示例三
    //var dataSet = await "PROC_Name".SqlProcedureQueriesAsync(new { id = 1, age = 27 });

    #endregion

    #region 返回Tuple<T1,...T8>

    // SqlProcedureQueries：执行存储过程返回元组集合 返回结果：元组类型

    //// ==== 同步操作 ====

    //// 示例一
    //var persons = "PROC_Name".SqlProcedureQueries<Person>();

    //// 示例二
    //var(persons, students) = "PROC_Name".SqlProcedureQueries<Person, Student>(new {id = 1});

    //// 示例三
    //var(persons, students, string) = "PROC_Name".SqlProcedureQueries<Person, Student, string>(new { id = 1, age = 27 });

    //// 示例四
    //var(persons, students, personDetail, string) = "PROC_Name".SqlProcedureQueries<Person, Student, PersonDetail, string>(new { id = 1, age = 27 });

    //// ==== 异步操作 ====

    //// 示例一
    //var persons = await "PROC_Name".SqlProcedureQueriesAsync<Person>();

    //// 示例二
    //var (persons, students) = await "PROC_Name".SqlProcedureQueriesAsync<Person, Student>(new { id = 1 });

    //// 示例三
    //var(persons, students, string) = await "PROC_Name".SqlProcedureQueriesAsync<Person, Student, string>(new { id = 1, age = 27 });

    //// 示例四
    //var(persons, students, personDetail, string) = await "PROC_Name".SqlProcedureQueriesAsync<Person, Student, PersonDetail, string>(new { id = 1, age = 27 });

    #endregion

    #region 返回单行单列

    // SqlProcedureScalar：执行存储过程返回单行单列 返回结果：object

    //// ==== 同步操作 ====

    //// 示例一
    //var value = "PROC_Name".SqlProcedureScalar(new { id = 1 });

    //// 示例二
    //var value = "PROC_Name".SqlProcedureScalar<string>(new { id = 1, name = "新生帝", address = "广东省中山市" });

    //// 示例三
    //var value = "PROC_Name".SqlProcedureScalar<int>(new { id = 1, address = "广东省中山市" });

    //// ==== 异步操作 ====

    //// 示例一
    //var value = await "PROC_Name".SqlProcedureScalarAsync(new { id = 1 });

    //// 示例二
    //var value = await "PROC_Name".SqlProcedureScalarAsync<string>(new { id = 1, name = "新生帝", address = "广东省中山市" });

    //// 示例三
    //var value = await "PROC_Name".SqlProcedureScalarAsync<int>(new { id = 1, address = "广东省中山市" });

    #endregion

    #region 返回受影响行数

    // SqlProcedureNonQuery：执行存储过程无数据返回 返回结果：int

    //// ==== 同步操作 ====

    //// 示例一
    //var rowEffects = "PROC_Name".SqlProcedureNonQuery(person);

    //// 示例二
    //var rowEffects = "PROC_Name".SqlProcedureNonQuery(new { id = 1, name = "新生帝", address = "广东省中山市" });

    //// 示例三
    //var rowEffects = "PROC_Name".SqlProcedureNonQuery(new { id = 1, name = "百小僧" });

    //// 示例四
    //var rowEffects = "PROC_Name".SqlProcedureNonQuery(new { id = 1 });

    //// ==== 异步操作 ====

    //// 示例一
    //var rowEffects = await "PROC_Name".SqlProcedureNonQueryAsync(person);

    //// 示例二
    //var rowEffects = await "PROC_Name".SqlProcedureNonQueryAsync(new { id = 1, name = "新生帝", address = "广东省中山市" });

    //// 示例三
    //var rowEffects = await "PROC_Name".SqlProcedureNonQueryAsync(new { id = 1, name = "百小僧" });

    //// 示例四
    //var rowEffects = await "PROC_Name".SqlProcedureNonQueryAsync(new { id = 1 });

    #endregion

    #region 带OUTPUT/RETURN返回

    //CREATE PROC PROC_Output
    //    @Id INT,    // 输入参数
    //    @Name NVARCHAR(32) OUTPUT,  // 输出参数，还带长度
    //    @Age INT OUTPUT // 输出参数
    //AS
    //BEGIN
    //    SET @Name = 'Furion Output';

    //    // 输出结果集
    //    SELECT*
    //    FROM dbo.Test
    //    WHERE Id > @Id;

    //    // 输出结果集
    //    SELECT TOP 10
    //           *
    //    FROM dbo.Test;

    //    SET @Age = 27;

    //    // 带 RETURN 返回
    //    RETURN 10;
    //END;

    // SqlProcedureOutput：执行存储过程返回OUTPUT、RETURN、结果集 返回结果：ProcedureOutput

    //// ==== 同步操作 ====

    //// 示例一
    //ProcedureOutputResult result = "PROC_Name".SqlProcedureOutput(new ProcOutputModel { Id = 1 });

    //// 示例二
    //ProcedureOutputResult result = "PROC_Name".SqlProcedureOutput(new ProcOutputModel { Id = 1 });

    //// 示例三
    //ProcedureOutputResult<(List<Person>, List<Student>)> result = "PROC_Name".SqlProcedureOutput<(List<Person>, List<Student>)>(new ProcOutputModel { Id = 1 });

    //// ==== 异步操作 ====
    //// 示例一
    //ProcedureOutputResult result = await "PROC_Name".SqlProcedureOutputAsync(new ProcOutputModel { Id = 1 });

    //// 示例二
    //ProcedureOutputResult result = await "PROC_Name".SqlProcedureOutputAsync(new ProcOutputModel { Id = 1 });

    //// 示例三
    //ProcedureOutputResult<(List<Person>, List<Student>)> result = await "PROC_Name".SqlProcedureOutputAsync<(List<Person>, List<Student>)>(new ProcOutputModel { Id = 1 });

    #endregion

    #endregion

    #region 懒人无敌函数

    #region 标量函数

    // SqlFunctionScalar：执行标量函数返回单行单列 返回结果：object/TResult

    //// ==== 同步操作 ====

    //// 示例一
    //var value = "FN_Name".SqlFunctionScalar();

    //// 示例二
    //var value = "FN_Name".SqlFunctionScalar(new { id = 1 });

    //// 示例三
    //var value = "FN_Name".SqlFunctionScalar<string>();

    //// 示例四
    //var value = "FN_Name".SqlFunctionScalar<int>(new { id = 1 });

    //// ==== 异步操作 ====

    //// 示例一
    //var value = await "FN_Name".SqlFunctionScalarAsync();

    //// 示例二
    //var value = await "FN_Name".SqlFunctionScalarAsync(new { id = 1 });

    //// 示例三
    //var value = await "FN_Name".SqlFunctionScalarAsync<string>();

    //// 示例四
    //var value = await "FN_Name".SqlFunctionScalarAsync<int>(new { id = 1 });

    #endregion

    #region 表值函数

    // SqlFunctionQuery：执行表值函数返回DataTable/List集合 返回结果：DataTable/List{T}

    // ==== 同步操作 ====

    //// 示例一
    //var dataTable = "FN_Name".SqlFunctionQuery();

    //// 示例二
    //var dataTable = "FN_Name".SqlFunctionQuery(new { id = 1 });

    //// 示例三
    //var persons = "FN_Name".SqlFunctionQuery<Person>();

    //// 示例四
    //var persons = "FN_Name".SqlFunctionQuery<Person>(new { id = 1 });

    //// ==== 异步操作 ====

    //// 示例一
    //var dataTable = await "FN_Name".SqlFunctionQueryAsync();

    //// 示例二
    //var dataTable = await "FN_Name".SqlFunctionQueryAsync(new { id = 1 });

    //// 示例三
    //var persons = await "FN_Name".SqlFunctionQueryAsync<Person>();

    //// 示例四
    //var persons = await "FN_Name".SqlFunctionQueryAsync<Person>(new { id = 1 });

    #endregion

    #endregion

    #region 设置超时时间

    // SetCommandTimeout：设置ADO.NET超时时间
    // SqlQuery：Sql查询返回DataTable 返回结果：DataTable
    //var data = "select * from table".SetCommandTimeout(100).SqlQuery(); // 单位秒

    #endregion

    #region ISqlRepository操作

    // ISqlRepository仓储是专门处理Sql操作的，无需实体方式，所有接口和懒人无敌方式一样

    //// 示例一
    //var dataTable = sqlRepository.SqlQuery("select * from person");

    //// 示例二
    //var dataTable = sqlRepository.SqlQuery("select * from person where id > @id", new { id = 10 });

    //// 示例四
    //var persons = sqlRepository.SqlQuery<Person>("select * from person");

    //// 示例五
    //var persons = sqlRepository.SqlQuery<Person>("select * from person where id > @id", new { id = 10 });

    // 不再举例子。。。

    #endregion

    #region IRepository操作

    // IRepository也能操作sql，调用方法也是和上面一致的
    // var dataTable = repository.Sql().SqlQuery("select * from person");

    #endregion

    #region IRepository<TEntity>操作

    // IRepository<TEntity>也能操作sql，调用方法也是和上面一致的
    // var dataTable = personRepository.SqlQuery("select * from person");

    #endregion

    #region 关于Sql参数

    // 所有sql、存储过程，函数参数都支持四种方式：
    // 1）DbParameter[]：数组类型
    // 2）new {}：匿名类型
    // 3）new Class{ }：强类型类型（支持复杂存储过程参数）
    // 4）Dictionary<string, object>类型

    // Tip：建议除了复杂的存储过程（带 OUTPUT/RETURN）的以外，所有参数建议使用new {}匿名类型，如果需要动态参数，则可以使用Dictionary<string,object>类型。

    #endregion

    #region 多数据库Sql操作

    #region 懒人无敌 🐮 方式

    //var dataTable = "select * from person".Change<MySqlDbContextLocator>().SqlQuery();

    //var persons = "select * from person whre id > @id".Change<SqliteDbContextLocator>().SqlQuery<Person>();

    // 【注】懒人方式只需要通过Change<TDbContextLocator> 方式即可动态切换数据库

    #endregion

    #region ISqlRepository方式

    // 只需要通过ISqlRepository<TDbContextLocator>注入或通过sqlRepository.Change<TDbContextLocator>()切换

    #endregion

    #region IRepository方式

    //只需要通过repository.Change<TDbContextLocator>()获取即可

    #endregion

    #region IRepository<TEntity>方式

    //只需要通过IRepository<TEntity, TDbContextLocator>注入或通过personRepository.Change<TEntity, TDbContextLocator>()切换

    #endregion

    #endregion

    #region 切换数据库

    //在Furion框架中，不管是懒人模式还是仓储模式都是通过.Change<TDbContextLocator>方式切换数据库

    //// 懒人模式
    //var data = "select * from table".Change<MySqlDbContextLocator>().SqlQuery<Data>();

    //// 仓储方式
    //var data = req.Change<MySqlDbContextLocator>().SqlQuery<Data>("select * from table");

    #endregion

    #region 多线程共享作用域

    // 默认情况下，所有的字符串和实体拓展都有自己独立维护的ServiceProvider作用域。
    // 在Web请求中，默认是HttpContext.RequestServices，但在非Web，如多线程操作，后台任务，事件总线等场景下会自动创建新的作用域，实际上这是非常不必要的内存开销。
    // 这时，我们只需要通过.SetXXXScoped(service)共享当前服务提供器作用域即可

    // Scoped.Create((fac, scope) => {
    // "select * from table".SetContextScoped(scope.ServiceProvider).SqlQuery();
    // });

    #endregion

    #region 静态Default方式构建

    //SqlExecutePart.Default.SetSqlString("select * from person").SqlQuery();

    #endregion

    #endregion

    #region Sql模板

    // Sql模板
    // 通常我们程序中执行数据库的sql语句都写在了程序集中，随程序一起编译，后续需要修改，则重新编译代码。
    // 所以，Furion创造出一种Sql模板的方式，程序执行Sql时，只需要使用特殊标记即可：#(模板Key)，这些真实的Sql配置在.json或.xml配置文件中

    #region 常规使用

    //// 仓储方式
    //var users = repository.SqlQuery<User>("#(Select.User)", new { id = 1 });

    //// 懒人方式
    //var users = "#(Select.User)".SqlQuery<User>(new { id = 1 });

    //// Sql 代理方式
    //[SqlExecute("#(Select.User)")]
    //List<User> GetUser(int id);

    #endregion

    #region 高级嵌套

    //var users = repository.SqlQuery<User>(
    //@"select * from user u
    //left join #(User.Detail) d on u.Id = d.UserId
    //where id > @id");

    #endregion

    #region Sql模板配置

    // 普通模式
    //{
    //  "Select.User": "select * from User"
    //}

    #endregion

    #endregion

    #region Sql高级代理

    // ISqlDispatchProxy接口是Furion实现被代理接口的唯一依赖，任何公开的接口一旦集成了ISqlDispatchProxy接口，那么这个接口就是被托管拦截的Sql操作接口。

    #endregion

    #region 多数据库使用方式

    // Furion通过独创的数据库上下文定位器 实现多数据库灵活操作切换。只需要为每一种数据库绑定唯一的数据库上下文定位器即可

    #region 实体仓储方式

    //// 切换到 MSSQL 操作 Person表
    //var mssqlRepository = personRepository.Change<Person, MsSqlDbContextLocator>();

    //// 切换到 MySql 操作 Person表
    //var mysqlRepository = personRepository.Change<Person, MySqlDbContextLocator>();

    //// 切换到 Sqlite 操作 Person表
    //var sqliteRepository = personRepository.Change<Person, SqliteDbContextLocator>();


    #endregion

    #region 非泛型仓储方式

    //// 切换到 MSSQL 操作 Person表
    //var mssqlRepository = repository.Change<Person, MsSqlDbContextLocator>();

    //// 切换到 MySql 操作 Person表
    //var mysqlRepository = repository.Change<Person, MySqlDbContextLocator>();

    //// 切换到 Sqlite 操作 Person表
    //var sqliteRepository = repository.Change<Person, SqliteDbContextLocator>();

    #endregion

    #region Sql仓储方式

    //// 切换到 MSSQL 操作 Person表
    //var mssqlRepository = sqlRepository.Change<MsSqlDbContextLocator>();

    //// 切换到 MySql 操作 Person表
    //var mysqlRepository = sqlRepository.Change<MySqlDbContextLocator>();

    //// 切换到 Sqlite 操作 Person表
    //var sqliteRepository = sqlRepository.Change<SqliteDbContextLocator>();

    #endregion

    #region 实体定义方式

    /// <summary>
    /// 支持一个数据库
    /// </summary>
    public class PersonTest : IEntity<MySqlDbContextLocator>
    {
        // ....
    }

    /// <summary>
    /// 支持多个数据库
    /// </summary>
    public class Person2 : IEntity<MySqlDbContextLocator, SqliteDbContextLocator>
    {
        // ....
    }

    // 所有的实体依赖接口或抽象类都支持泛型方式 指定 数据库上下文定位器，最多支持 8 个

    #endregion

    #region Linq函数方式

    public static class QueryFunctionsWithLinq
    {
        [QueryableFunction("FN_GetId", "dbo", typeof(MySqlDbContextLocator), typeof(SqliteDbContextLocator))]
        public static int GetId(int id) => throw new NotSupportedException();
    }

    #endregion

    #region MySQL时区问题/少8小时问题

    // issue解决链接：https://gitee.com/dotnetchina/Furion/issues/I3RSCO

    // 参考链接
    // https://github.com/PomeloFoundation/Pomelo.EntityFrameworkCore.MySql/issues/819#issuecomment-531132122
    // https://docs.microsoft.com/zh-cn/ef/core/modeling/value-conversions?tabs=data-annotations#built-in-converters

    #endregion

    #endregion

    #region 模型生成数据库（Code First）

    // 模型生成数据库（Code First）-- 正向工程：https://dotnetchina.gitee.io/furion/docs/dbcontext-code-first/
    // 程序包管理控制台命令：
    // 1）创建模型版本：Add-Migration v1.0.0
    // 2）更新到数据库：Update-Database  （如果 Update-Database 后面带字符串参数，则会自动还原数据库到指定版本，如： Update-Database v0.0.3 将数据库还原到 v0.0.3 版本）
    // 3）导出Sql：Script-Migration

    // 特别注意
    // Furion 框架默认数据迁移的程序集为：Furion.Database.Migrations，所以如果您改了程序集名称或通过 Nuget 方式安装的 Furion 包，则需要配置迁移程序集名称：
    //services.AddDatabaseAccessor(options =>
    //{
    //    options.AddDbPool<FurionDbContext>(DbProvider.Sqlite);
    //}, "存放迁移文件的项目名称");
    //另外，如果应用中配置了多个数据库上下文，那么所有的 迁移命令 都需要指定 -Context 数据库上下文名称 参数。如：

    //Add-Migration v1.0.0 -Context FurionDbContext

    #endregion

    #region 数据库生成模型（Db First）

    // 数据库生成模型（Db First）-- 逆向工程：https://dotnetchina.gitee.io/furion/docs/dbcontext-db-first/
    // tools/cli.ps1
    // 程序包管理控制台命令：Show-Command ../tools/cli.ps1

    #endregion
}
